<?php
namespace Services\Sys;

use Helpers\Di;
use Helpers\User;
use Helpers\Tool;
use Helpers\Main;
use Helpers\Session;
use Services\Sys\Models\XhsysPower;
use Services\Sys\Models\XhsysTree;
use Services\Sys\Models\XhsysUserpower;
use Services\Sys\Models\XhsysGroupuser;
use Services\Sys\Models\XhsysGrouppower;
use Services\Sys\Models\XhsysUserextrapower;

class Power implements PowerInterface
{

    public static $groupEnum = [
        'iType' => [1 => '系统组', 2 => '角色组', 3 => '教师组']
    ];

    /**
     * 检查是否有权限
     * todo 支持多权限判断
     *
     * @param $powerTag
     * @param null $targetId    -- userId(默认)|groupId
     * @param null $type        -- user(仅用户)|group(仅组)|all(默认)
     * @return bool
     *
     * create by ck 20180607
     * modify by ck 20180613
     */
    public static function exist($powerTag, $targetId = null, $type = null)
    {
        $targetId or $targetId = User::getId();
        if ($targetId == User::getId() && User::isAdmin()) {
            return true;
        }
        return in_array($powerTag, self::getPowerTags($targetId, $type));
    }

    /**
     * 获取权限标识列表（默认合并用户组）
     * 静态保存，登陆用户保存至session
     *
     * @param null $targetId
     * @param null $type
     * @return mixed
     *
     * create by ck 20180608
     */
    public static function getPowerTags($targetId = null, $type = null)
    {
        switch ($type) {
            case 'user':
                return self::getUserPowerTags($targetId);
            case 'group':
                return self::getGroupPowerTags($targetId);
        }

        static $powerTags = [];
        $targetId or $targetId = User::getId();
        if (!$targetId) {
            return [];
        }
        if (isset($powerTags[$targetId])) {
            return $powerTags[$targetId];
        }
        if ($targetId == User::getId() && Session::has('powerTags')) {
            $powerTags[$targetId] = Session::get('powerTags');
        }
        if (!isset($powerTags[$targetId])) {
            $powerTags[$targetId] = self::getUserPowerTags($targetId);
            $groupIds = self::getUserGroupIds($targetId);
            if ($groupIds) {
                $powerTags[$targetId] = array_values(array_unique(array_merge(
                    $powerTags[$targetId],
                    self::getGroupPowerTags($groupIds)
                )));
            }
        }
        if ($targetId == User::getId() && !Session::has('powerTags') && User::getId()) {
            Session::set('powerTags', $powerTags[$targetId]);
        }
        return $powerTags[$targetId];
    }

    /**
     * 获取扩展权限id
     *
     * @param $type
     * @param $target
     * @param null $userId
     * @return array|bool|mixed
     *
     * create by ck 20180611
     * modify by ck 20180622
     * modify by ck 20180822    合并查看管理权限
     */
    public static function getExtraPower($type, $target, $userId = null)
    {
        $userId = $userId ?: User::getId();
        if ($userId == User::getId() && User::isAdmin()) {
            return true;
        }

        $cacheKey = "extraPower[{$type}][{$target}][{$userId}]";
        if (Session::has($cacheKey)) {
            return Session::get($cacheKey);
        }

        //获取用户扩展权限
        $userViewPower   = self::getUserExtraPower($type, $target, $userId, 0);
        $userManagePower = self::getUserExtraPower($type, $target, $userId, 1);
        if ($userViewPower === true || $userManagePower === true) {
            $powerIds = true;
            goto returnTrue;
        }
        $powerIds =  array_values(array_unique(array_merge($userViewPower, $userManagePower)));

        //获取组扩展权限
        $groupIds = self::getUserGroupIds($userId);
        if ($groupIds) {
            $groupViewPower   = self::getGroupExtraPower($type, $target, $groupIds, 0);
            $groupManagePower = self::getGroupExtraPower($type, $target, $groupIds, 1);
            if ($groupViewPower === true || $groupManagePower === true) {
                $powerIds = true;
                goto returnTrue;
            }
            $powerIds = array_values(array_unique(array_merge($powerIds, $groupViewPower, $groupManagePower)));
        }

        returnTrue:
            Session::set($cacheKey, $powerIds);
            return $powerIds;
    }

    /**
     * 获取扩展管理权限id
     *
     * @param $type
     * @param $target
     * @param null $userId
     * @return array|bool|mixed
     *
     * create by ck 20181121
     */
    public static function getManageExtraPower($type, $target, $userId = null)
    {
        $userId = $userId ?: User::getId();
        if ($userId == User::getId() && User::isAdmin()) {
            return true;
        }

        //获取用户扩展权限
        $powerIds = self::getUserExtraPower($type, $target, $userId, 1);
        if ($powerIds === true) {
            goto returnTrue;
        }

        //获取组扩展权限
        $groupIds = self::getUserGroupIds($userId);
        if ($groupIds) {
            $groupPowerIds = self::getGroupExtraPower($type, $target, $groupIds, 1);
            if ($groupPowerIds === true) {
                $powerIds = true;
                goto returnTrue;
            }
            $powerIds = array_values(array_unique(array_merge($powerIds, $groupPowerIds)));
        }

        returnTrue:
        return $powerIds;
    }


    /**
     * 获取用户所属组id
     *
     * @param null $userId
     * @return array
     *
     * create by ck 20180608
     * modify by ck 20180613
     */
    private static function getUserGroupIds($userId = null)
    {
        static $userGroup = [];
        $userId or $userId = User::getId();
        if (isset($userGroup[$userId])) {
            return $userGroup[$userId];
        }
        $groupIds = XhsysGroupuser::find([
            'columns'    => 'iGroupId',
            'conditions' => 'bDelete = 0 AND iUserId = :userId:',
            'bind'       => ['userId' => $userId]
        ])->toArray();
        $userGroup[$userId] = array_column($groupIds, 'iGroupId');
        return $userGroup[$userId];
    }

    /**
     * 获取用户权限
     *
     * @param null $userId
     * @return mixed
     *
     * create by ck 20180608
     */
    private static function getUserPowerTags($userId = null)
    {
        static $powerTags = [];
        $userId or $userId = User::getId();
        if (isset($powerTags[$userId])) {
            return $powerTags[$userId];
        }
        $powerTags[$userId] = [];
        $userPower = XhsysUserpower::findFirst([
            'columns'    => 'mUPowerTag',
            'conditions' => 'bDelete = 0 AND iUPUserId = :userId:',
            'bind'       => ['userId' => $userId]
        ]);
        if ($userPower) {
            $powerTags[$userId] = array_filter(explode(',', $userPower->mUPowerTag));
        }
        return $powerTags[$userId];
    }

    /**
     * 获取组权限
     *
     * @param $groupIds
     * @return array
     * @throws \Exception
     *
     * create by ck 20180608
     * modify by ck 20180614    添加缓存
     */
    private static function getGroupPowerTags($groupIds)
    {
        static $powerTags = [];
        if (!$groupIds) {
            throw new \Exception('组id不能为空');
        }
        $tags = [];
        is_array($groupIds) or $groupIds = [$groupIds];
        foreach ($groupIds as $index => $groupId) {
            if (isset($powerTags[$groupId])) {
                $tags = array_merge($tags, $powerTags[$groupId]);
                unset($groupIds[$index]);
            }
        }
        if ($groupIds) {
            $groupPower = XhsysGrouppower::find([
                'columns'    => 'iGroupId,mPowerTag',
                'conditions' => 'bDelete = 0 AND iGroupId IN ({groupId:array})',
                'bind'       => ['groupId' => $groupIds]
            ])->toArray();
            $groupPower = array_column($groupPower, 'mPowerTag', 'iGroupId');
            foreach ($groupPower as $groupId => $power) {
                $powerTags[$groupId] = explode(',', $power);
                $tags = array_merge($tags, $powerTags[$groupId]);
            }
        }
        return array_values(array_unique($tags));
    }

    /**
     * 获取用户扩展权限
     *
     * @param $type
     * @param $target
     * @param null $userId
     * @param int $manage
     * @return array|bool|mixed
     *
     * create by ck 20180611
     * modify by ck 20180613    bug修复
     * modify by ck 20180822    区分查看/管理
     */
    private static function getUserExtraPower($type, $target, $userId = null, $manage = 0)
    {
        static $powerTags = [];
        $userId or $userId = User::getId();
        if (isset($powerTags[$type][$target][$userId][$manage])) {
            return $powerTags[$type][$target][$userId][$manage];
        }
        $powerTags[$type][$target][$userId][$manage] = [];
        $userPower = XhsysUserextrapower::findFirst([
            'conditions' => 'bDelete = 0 AND iGoal = 1 AND sType = :type: AND sTarget = :target: 
                AND iGoalId = :userId: AND bManage = :manage:',
            'bind'       => ['userId' => $userId, 'type' => $type, 'target' => $target, 'manage' => $manage]
        ]);
        if (!$userPower) {
            return [];
        }
        if ($userPower->bAll) {
            return true;
        }
        if ($userPower) {
            $powerTags[$type][$target][$userId][$manage] = $userPower->mContent;
        }
        return $powerTags[$type][$target][$userId][$manage];
    }

    /**
     * 获取组扩展权限
     *
     * @param $type
     * @param $target
     * @param $groupId
     * @param int $manage
     * @return array|bool
     * @throws \Exception
     *
     * create by ck 20180611
     */
    private static function getGroupExtraPower($type, $target, $groupId, $manage = 0)
    {
        if (!$groupId) {
            throw new \Exception('组id不能为空');
        }
        is_array($groupId) or $groupId = [$groupId];
        $powerTags = [];
        $groupPower = XhsysUserextrapower::find([
            'conditions' => 'bDelete = 0 AND iGoal = 2 AND sType = :type: AND sTarget = :target: 
                AND iGoalId IN ({groupId:array}) AND bManage = :manage:',
            'bind'       => ['groupId' => $groupId, 'type' => $type, 'target' => $target, 'manage' => $manage]
        ]);
        foreach ($groupPower as $power) {
            if ($power->bAll) {
                return true;
            }
            $powerTags = array_merge($powerTags, $power->mContent);
        }
        return array_values(array_unique($powerTags));
    }

    /**
     * 判断是否有管理权限
     *
     * @param $type
     * @param $target
     * @param $id
     * @param bool $manage
     * @return bool
     *
     * create by ck 20180822
     */
    public static function hasExtra($type, $target, $id, $manage = false)
    {
        $userId = User::getId();
        if ($userId == User::getId() && User::isAdmin()) {
            return true;
        }

        if (!$manage) {
            $powerIds = self::getExtraPower($type, $target, $userId);
            goto dealPower;
        }

        //处理管理权限
        $cacheKey = "extraManagePower[{$type}][{$target}]";
        if (Session::has($cacheKey)) {
            $powerIds = Session::get($cacheKey);
            goto dealPower;
        }

        //获取用户扩展权限
        $powerIds = self::getUserExtraPower($type, $target, $userId, 1);
        if ($powerIds === true) {
            goto dealPower;
        }

        //获取组扩展权限
        $groupIds = self::getUserGroupIds($userId);
        if ($groupIds) {
            $groupPower = self::getGroupExtraPower($type, $target, $groupIds, 1);
            if ($groupPower === true) {
                $powerIds = true;
                goto dealPower;
            }
            $powerIds = array_values(array_unique(array_merge($powerIds, $groupIds)));
        }
        Session::set($cacheKey, $powerIds);

        dealPower:
        if ($powerIds === true) {
            return true;
        }
        return in_array($id, $powerIds);
    }

    /**
     * 根据节点id获取权限信息
     *
     * @param $nodeId
     * @return array
     * @throws \Exception
     *
     * create by ck 20190108
     */
    public static function getNodePowerInfo($nodeId)
    {
        $node = XhsysTree::findFirst($nodeId);
        if (!$node) {
            throw new \Exception('无节点信息');
        }
        $data = [
            'powerNodeId'   => $node->iNodeId,
            'powerNodeName' => $node->sNodeName
        ];
        $powers = XhsysPower::find([
            'columns'    => 'iPowerId,sPowerTag,sPowerName,sExtraUrl,bPowerMain',
            'conditions' => 'iNodeId = :nodeId:',
            'bind'       => ['nodeId' => $nodeId]
        ])->toArray();
        if ($powers) {
            foreach ($powers as $power) {
                if ($power['bPowerMain']) {
                    $data['mainPowerTag']  = $power['sPowerTag'];
                    $data['mainPowerName'] = $power['sPowerName'];
                    $data['mainExtraUrl']  = $power['sExtraUrl'];
                } else {
                    $data['extra'][] = [
                        'powerTag'  => $power['sPowerTag'],
                        'powerName' => $power['sPowerName'],
                    ];
                }
            }
        }
        return $data;
    }

    /**
     * 保存节点权限
     *
     * @param $nodeId
     * @param array $mainPower
     * @param array $extraPower
     * @throws \Exception
     *
     * create by ck 20190108
     */
    public static function saveNodePower($nodeId, array $mainPower, array $extraPower = [])
    {
        try {
            Di::get()->db->begin();
            //删除原权限
            XhsysPower::find([
                'conditions' => 'iNodeId = :nodeId:',
                'bind'       => ['nodeId' => $nodeId]
            ])->delete();

            //检查是否重复
            $existPower = XhsysPower::count([
                'columns'    => 'sPowerTag',
                'conditions' => 'sPowerTag IN ({powerTags:array})',
                'bind'       => [
                    'powerTags' => array_merge([$mainPower['tag']], array_filter(array_keys($extraPower)))
                ]
            ]);
            if ($existPower) {
                throw new \Exception('权限已存在');
            }

            //处理主权限
            $power = new XhsysPower(['iNodeId' => $nodeId, 'bPowerMain' => 1]);
            $power->sPowerTag  = $mainPower['tag'];
            $power->sPowerName = $mainPower['name'];
            $power->sExtraUrl  = $mainPower['extraUrl'];
            if (!$power->save()) {
                throw new \Exception($power->getError());
            }

            //处理其他权限
            foreach ($extraPower as $tag => $name) {
                if (!$tag || !$name) {
                    continue;
                }
                $power = new XhsysPower(['iNodeId' => $nodeId]);
                $power->sPowerTag  = $tag;
                $power->sPowerName = $name;
                if (!$power->save()) {
                    throw new \Exception($power->getError());
                }
            }
            Di::get()->db->commit();
        } catch (\Exception $e) {
            Di::get()->db->rollback();
            throw new \Exception($e->getMessage());
        }
    }
}
